﻿// Inner Fire 游戏引擎库
// CameraObject - 摄像机对象
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层（4）
// 用于游戏的摄像机。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-25

#include "camera_object.h"
#include "game/manager/game_manager.h"
#include "game/manager/scene.h"

using namespace DirectX;

namespace ifire::game {

CameraObject::CameraObject(ikit::sstr name, Scene* scene, GameObject* parent)
    : GameObject(name, scene, parent) {
  // 从系统中获得Camera进行操作
  camera_ = &scene->GM()->GetGraphics()->GetView().GetCamera();
}

CameraObject::~CameraObject() {}

void CameraObject::FixedUpdate() {}

void CameraObject::SetCameraParam(float fov, float near_z, float far_z) {
  // FOV需要从角度转化为弧度
  camera_->SetLens(fov * RAD_TO_DEG, camera_->GetAspect(), near_z, far_z);
}

void CameraObject::SetCameraRotation(float pitch, float yaw, float roll) {
  pitch_ = pitch;
  yaw_ = yaw;
  roll_ = roll;

  UpdateFollow();
}

void CameraObject::SetFollow(Transform* transform) { follow_ = transform; }

XMVECTOR CameraObject::GetOrientationQuaternion() const {
  // 这三个项目是以角度为单位的，所以需要转化弧度
  float p = XMConvertToRadians(pitch_);
  float y = XMConvertToRadians(yaw_);
  float r = XMConvertToRadians(roll_);
  return XMQuaternionRotationRollPitchYaw(p, y, r);
}

void CameraObject::UpdateFollow() {
  // 如果没有follow，则不计算
  if (!follow_) {
    return;
  }

  // 1. 欧拉角转四元数（ZYX顺序）[6,7](@ref)
  XMVECTOR quat = XMQuaternionRotationRollPitchYaw(XMConvertToRadians(pitch_),
      XMConvertToRadians(yaw_), XMConvertToRadians(roll_));

  // 2. 计算相机位置：目标位置 + 旋转后的偏移量
  auto target_positon = follow_->GetPosition();
  XMVECTOR target = XMLoadFloat3(&target_positon);
  XMVECTOR offset = XMLoadFloat3(&offset_);
  XMVECTOR rotated_offset = XMVector3Rotate(offset, quat);
  XMVECTOR position = target + rotated_offset;

  // 3. 存储到成员变量
  XMStoreFloat3(&look_position_, position);
  XMStoreFloat4(&look_rotation_, quat);

  // 更新到相机
  camera_->SetCamera(position, quat);
}

void CameraObject::SetOffset(const DirectX::XMFLOAT3& offset) {
  offset_ = offset;
}

XMFLOAT3 CameraObject::TransformAxis(const DirectX::XMFLOAT2& axis) const {
  // 1. 获取相机坐标系轴向量
  XMVECTOR right = XMLoadFloat3(&camera_->right_);
  XMVECTOR look = XMLoadFloat3(&camera_->look_);

  // 2. 忽略Y轴影响（投影到XZ平面）
  right = XMVectorSetY(right, 0.0f);
  look = XMVectorSetY(look, 0.0f);

  // 3. 标准化平面向量
  right = XMVector3Normalize(right);
  look = XMVector3Normalize(look);

  // 4. 组合输入轴分量
  XMVECTOR direction = right * axis.x + // 左右移动分量
                       look * axis.y;   // 前后移动分量

  // 5. 标准化最终方向
  direction = XMVector3Normalize(direction);

  // 6. 存储结果
  XMFLOAT3 result;
  XMStoreFloat3(&result, direction);
  return result;
}

} // namespace ifire::game
